package de.idgard.android.addon.ui;

import java.util.UUID;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.google.web.bindery.requestfactory.shared.Receiver;
import com.google.web.bindery.requestfactory.shared.ServerFailure;

import de.idgard.android.R;
import de.idgard.android.addon.services.GlobalServiceRegistry;
import de.idgard.android.addon.ui.dialogs.IDGardUpdateDialog;
import de.idgard.android.addon.ui.services.BrowserUtilityService;
import de.idgard.android.addon.ui.services.PreferenceService;
import de.idgard.android.addon.ui.services.PropertiesService;
import de.idgard.android.addon.ui.services.dto.IDGardCookieDTO;
import de.idgard.webapp.common.client.model.KeyValueProxy;
import de.idgard.webapp.user.client.service.LoginServiceRF.LoginService;

/**
 * 
 * @author <a href="mailto:vesko.georgiev@uniscon.com">Vesko Georgiev</a>
 * @author pratik popat - code modified for layout adjustment.
 */
public class LoginActivity extends Activity implements TextView.OnEditorActionListener {

	private EditText username;
	private EditText password;
	private TextView errorLabel;
	private ProgressBar progressbarLogin, pbLoginHorizontal;

	private PreferenceService getPreferenceService() {
		return GlobalServiceRegistry.instance().getPreferenceService();
	}

	private PropertiesService getPropertiesService() {
		return GlobalServiceRegistry.instance().getPropertiesService();
	}

	private BrowserUtilityService getBrowserUtilityService() {
		return GlobalServiceRegistry.instance().getBrowserUtilityService();
	}

	@Override
	protected void onResume() {
		if (GlobalServiceRegistry.instance().getAddonStateService().isAddonON()) {
			finish();
		}
		super.onResume();
	}

	@Override
	protected Dialog onCreateDialog(int id) {
		switch (id) {
		case 1:
			return createNetworkNotOnlineDialog(this);
		default:
			return null;
		}
	}

	@Override
	protected Dialog onCreateDialog(int id, Bundle args) {
		switch (id) {
		case 2:
			return new IDGardUpdateDialog(this, args.getString("link"));
		default:
			return null;
		}
	}

	public boolean checkOnlineAndNotify() {
		boolean isOnline = AddonUIManager.getInstance().isOnline(this);
		if (!isOnline) {
			showDialog(1);
		}
		return isOnline;
	}

	public void checkForNewUpdates() {

		Runnable runnable = new Runnable() {

			@Override
			public void run() {
				try {
					String link = GlobalServiceRegistry.instance().getUpdateService().checkIfLatestVersionAndGetLinkUrl();
					if (link != null) {
						//
						Bundle b = new Bundle();
						b.putString("update", link);
						Message msg = new Message();
						msg.setData(b);
						if (handler != null) {
							handler.sendMessage(msg);
						}

					}
				} catch (Exception x) {

				}

			}
		};
		new Thread(runnable).start();

	}

	private Dialog createNetworkNotOnlineDialog(Context ctx) {
		Dialog dialog;

		AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
		builder.setMessage(getPropertiesService().getString(R.string.dialog_alert_desc_no_network))
				.setTitle(getPropertiesService().getString(R.string.dialog_alert_title_no_internet_connection)).setCancelable(false)
				.setPositiveButton("OK", new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int id) {
						Intent intent = new Intent(Settings.ACTION_WIRELESS_SETTINGS);
						startActivity(intent);
						dialog.dismiss();
					}
				}).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {

					@Override
					public void onClick(DialogInterface dialog, int which) {
						dialog.dismiss();
					}
				});

		dialog = builder.create();
		return dialog;
	}

	@Override
	protected void onPostResume() {
		boolean online = checkOnlineAndNotify();

		if (online) {
			checkForNewUpdates();
		}
		super.onPostResume();
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {

		requestWindowFeature(Window.FEATURE_NO_TITLE);
		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
		setContentView(R.layout.idgard_login);
		username = (EditText) findViewById(R.id.loginUsername);
		username.setOnEditorActionListener(this);
		username.setOnFocusChangeListener(new View.OnFocusChangeListener() {
			@Override
			public void onFocusChange(View v, boolean hasFocus) {
				if (hasFocus) {
					getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
				}
			}
		});

		password = (EditText) findViewById(R.id.loginPassword);
		password.setOnEditorActionListener(this);
		password.setOnFocusChangeListener(new View.OnFocusChangeListener() {
			@Override
			public void onFocusChange(View v, boolean hasFocus) {
				if (hasFocus) {
					getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
				}
			}
		});

		errorLabel = (TextView) findViewById(R.id.errorLabel);

		progressbarLogin = (ProgressBar) findViewById(R.id.loginProgress);
		pbLoginHorizontal = (ProgressBar) findViewById(R.id.pb_login_horizontal_bar);

		String user = getPreferenceService().getLastSavedUsername();
		username.setText(user);

		if (!TextUtils.isEmpty(user)) {
			password.requestFocus();
		}
		super.onCreate(savedInstanceState);
	}

	@Override
	public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
		if (actionId == EditorInfo.IME_ACTION_GO || actionId == 0) {
			startLogin(v);
			return true;
		}
		return false;
	}

	@Override
	public void onBackPressed() {
		AddonUIManager.getInstance().getContainerActivity().finish();
		this.finish();
		super.onBackPressed();
	}

	private void startLogin(View v) {
		if (username.getText().length() > 0 && password.getText().length() > 0) {
			progressbarLogin.setVisibility(View.VISIBLE);
			pbLoginHorizontal.setVisibility(View.VISIBLE);
			clearError();
			((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(v.getWindowToken(), 0);
			performLogin();
		} else {
			showError(getResources().getString(R.string.login_empty_fields_error));
		}
	}

	public void setLoginProgress(int progress) {
		pbLoginHorizontal.setProgress(progress);
	}

	private String getUsername() {
		return username.getText().toString();
	}

	private String getPassword() {
		return password.getText().toString();
	}

	private void clearError() {
		errorLabel.setText("");
	}

	private void showError(String message) {
		progressbarLogin.setVisibility(View.INVISIBLE);
		pbLoginHorizontal.setVisibility(View.INVISIBLE);
		errorLabel.setText(message);
	}

	final Handler handler = new Handler() {

		public void handleMessage(Message msg) {
			Object update = msg.getData().get("update");
			if (update != null) {
				Bundle b = new Bundle();
				b.putString("link", update.toString());
				try{
				showDialog(2, b);
				}catch (Exception e) {}
				getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
				return;
			}

			Object progress = msg.getData().get("progress");
			if (progress == null) {
				finish();
				return;
			}
			System.out.println("PROGRESS:" + progress);
			setLoginProgress((Integer) progress);
		}
	};

	private String generateCrossSiteForgeryPreventionToken(final String username) {
		return UUID.randomUUID().toString() + username;
	}

	private void performLogin() {
		LoginService loginService = GlobalServiceRegistry.instance().getLoginService();

		final String crossSiteForgeryPreventionCookie = generateCrossSiteForgeryPreventionToken(getUsername());

		loginService.login(getUsername(), getPassword(), null, null, crossSiteForgeryPreventionCookie).fire(new Receiver<KeyValueProxy>() {
			@Override
			public void onSuccess(KeyValueProxy res) {
				if (res.getKey().equals("2")) {
					String idgardKey = getPropertiesService().getString(R.string.idgardidcookie);
					String jsessionKey = getPropertiesService().getString(R.string.jsessionidcookie);
					String crossSiteKey = getPropertiesService().getString(R.string.crosssitepreventioncookie);

					IDGardCookieDTO idgData = getBrowserUtilityService().getIDGardData();
					String idgardCookie = idgardKey + "=" + idgData.getIdgardId();
					String jsessionCookie = jsessionKey + "=" + idgData.getJsessionId();
					String crossForgery = crossSiteKey + "=" + idgData.getCrossSitePrevention();

					if (!crossSiteForgeryPreventionCookie.equals(idgData.getCrossSitePrevention())) {

						GlobalServiceRegistry.instance().getBackendService().logoff().fire();
						showError(getPropertiesService().getString(R.string.err_wrong_credentials));
						return;
					}

					CookieSyncManager syncManager = CookieSyncManager.createInstance(LoginActivity.this);

					CookieManager cookieManager = CookieManager.getInstance();
					cookieManager.setAcceptCookie(true);
					cookieManager.removeAllCookie();

					// TODO:REMOVE AFTER TESTING
					SystemClock.sleep(1000);

					String domain = "https://" + getPropertiesService().getString(R.string.system_domain);
					cookieManager.setCookie(domain, idgardCookie);
					cookieManager.setCookie(domain, jsessionCookie);
					cookieManager.setCookie(domain, crossSiteForgeryPreventionCookie);

					syncManager.sync();

					getPreferenceService().saveUsername(username.getText().toString());

					AddonUIManager.getInstance().performLogin(handler);
				} else {
					showError(getPropertiesService().getString(R.string.err_wrong_credentials));
				}
			}

			@Override
			public void onFailure(ServerFailure error) {
				Log.w(getClass().getName(), error.getMessage() + "\n" + error.getStackTraceString());
				showError(error.getMessage());
			}
		});
	}

}
